#include <REGX52.H>
#include <intrins.h>

/**
 * 1. 实现Speed界面
 * 2. 实现左右按键，切换速度的功能
 */

// LCD引脚定义
#define LCD_DATA P0
sbit LCD_CS1 = P2^0;  // 左屏片选
sbit LCD_CS2 = P2^1;  // 右屏片选
sbit LCD_RS = P2^2;   // 数据/命令选择
sbit LCD_RW = P2^3;   // 读/写选择
sbit LCD_E = P2^4;    // 使能信号

// 按键引脚定义
sbit BTN_LEFT = P1^4;
sbit BTN_RIGHT = P1^5;

// 按键代码定义
#define BTN_CODE_NONE 0xFF
#define BTN_CODE_LEFT 4
#define BTN_CODE_RIGHT 5

// 速度等级定义
#define SPEED_MIN 1
#define SPEED_MAX 9
unsigned char current_speed = 5; // 当前速度，初始为5

unsigned char code NUM_CHARS[] = {
    0x7F, 0x41, 0x41, 0x7F, // 0字模
    0x00, 0x00, 0x00, 0x7F, // 1字模
    0x79, 0x49, 0x49, 0x4F, // 2字模
    0x49, 0x49, 0x49, 0x7F, // 3字模
    0x0F, 0x08, 0x08, 0x7F, // 4字模
    0x4F, 0x49, 0x49, 0x79, // 5字模
    0x7F, 0x49, 0x49, 0x79, // 6字模
    0x01, 0x01, 0x01, 0x7F, // 7字模
    0x7F, 0x49, 0x49, 0x7F, // 8字模
    0x4F, 0x49, 0x49, 0x7F, // 9字模
};

unsigned char code LEFT_ARROW[] = {0x08, 0x1c, 0x3e, 0x7f};
unsigned char code RIGHT_ARROW[] = {0x7f, 0x3e, 0x1c, 0x08};

// speed字模
unsigned char code SPEED_CHARS[] = {
    0x46, 0x49, 0x49, 0x31, 0x00, // S
    0x7F, 0x09, 0x09, 0x06, 0x00, // P
    0x7F, 0x49, 0x49, 0x49, 0x00, // E
    0x7F, 0x49, 0x49, 0x49, 0x00, // E
    0x7F, 0x41, 0x41, 0x3E, 0x00  // D
};

// 延时函数
void lcd_delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for (i = 0; i < ms; i++)
    {
        for (j = 0; j < 123; j++)
            ;
    }
}

void lcd_delay_us(unsigned int t)
{
    while (t--)
    {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    }
}

// LCD基础操作函数
bit lcd_read_busy(bit controller)
{
    bit is_busy = 0;
    LCD_DATA = 0xFF;
    LCD_RW = 1;
    LCD_RS = 0;

    LCD_CS1 = (controller == 1);
    LCD_CS2 = (controller == 0);

    LCD_E = 1;
    lcd_delay_us(2);
    is_busy = (LCD_DATA & 0x80) ? 1 : 0;
    LCD_E = 0;
    return is_busy;
}

void lcd_write_command(unsigned char cmd, unsigned char controller)
{
    while (lcd_read_busy(controller))
    {
        // 等待LCD准备好
    }

    LCD_DATA = cmd;
    LCD_RW = 0;
    LCD_RS = 0;

    LCD_CS1 = (controller == 1);
    LCD_CS2 = (controller == 0);

    LCD_E = 1;
    lcd_delay_us(2);
    LCD_E = 0;
}

void lcd_write_data(unsigned char dat, unsigned char controller)
{
    while (lcd_read_busy(controller))
    {
        // 等待LCD准备好
    }

    LCD_DATA = dat;
    LCD_RW = 0;
    LCD_RS = 1;

    LCD_CS1 = (controller == 1);
    LCD_CS2 = (controller == 0);

    LCD_E = 1;
    lcd_delay_us(2);
    LCD_E = 0;
}

void lcd_init()
{
    lcd_delay_ms(50);
    lcd_write_command(0x3F, 0); // 左屏开启
    lcd_write_command(0x3F, 1); // 右屏开启
    lcd_write_command(0xC0, 0); // 起始行
    lcd_write_command(0xC0, 1); // 起始行
}

void lcd_clear_screen()
{
    unsigned char page, col;

    // 清左屏
    for (page = 0; page < 8; page++)
    {
        lcd_write_command(0xB8 | page, 0);
        lcd_write_command(0x40, 0);
        for (col = 0; col < 64; col++)
            lcd_write_data(0x00, 0);
    }

    // 清右屏
    for (page = 0; page < 8; page++)
    {
        lcd_write_command(0xB8 | page, 1);
        lcd_write_command(0x40, 1);
        for (col = 0; col < 64; col++)
            lcd_write_data(0x00, 1);
    }
}

// 在指定页和列显示字节数组
void lcd_display_bytes_in_page(unsigned char page, unsigned char col,
                               unsigned char byte_arr[], unsigned int length)
{
    unsigned char i;
    if (col >= 64)
    {
        // 写cs2，不会跨屏
        lcd_write_command(0xB8 | page, 1);
        lcd_write_command(0x40 | col, 1);
        for (i = 0; i < length; i++)
        {
            lcd_write_data(byte_arr[i], 1);
        }
    }
    else if (col + length < 64)
    {
        // 写cs1，不会跨屏
        lcd_write_command(0xB8 | page, 0);
        lcd_write_command(0x40 | col, 0);
        for (i = 0; i < length; i++)
        {
            lcd_write_data(byte_arr[i], 0);
        }
    }
    else
    {
        // 跨屏显示
        // 先写cs1
        lcd_write_command(0xB8 | page, 0);
        lcd_write_command(0x40 | col, 0);
        for (i = 0; i < (64 - col); i++)
        {
            lcd_write_data(byte_arr[i], 0);
        }

        // 再写cs2
        lcd_write_command(0xB8 | page, 1);
        lcd_write_command(0x40, 1);
        for (i = 0; i < length - (64 - col); i++)
        {
            lcd_write_data(byte_arr[(64 - col) + i], 1);
        }
    }
}

// 按键扫描函数
unsigned char btn_scan()
{
    if (BTN_LEFT == 0)
    {
        lcd_delay_ms(20); // 消抖
        if (BTN_LEFT == 0)
        {
            while (BTN_LEFT == 0)
                ; // 等待按键释放
            return BTN_CODE_LEFT;
        }
    }

    if (BTN_RIGHT == 0)
    {
        lcd_delay_ms(20); // 消抖
        if (BTN_RIGHT == 0)
        {
            while (BTN_RIGHT == 0)
                ; // 等待按键释放
            return BTN_CODE_RIGHT;
        }
    }

    return BTN_CODE_NONE;
}

// 显示Speed文字
void display_speed_text()
{
    lcd_display_bytes_in_page(2, 30, SPEED_CHARS, sizeof(SPEED_CHARS));
}

// 显示当前速度数字
void display_speed_number()
{
    unsigned char *num_ptr = NUM_CHARS + current_speed * 4;
    lcd_display_bytes_in_page(4, 60, num_ptr, 4);
}

// 显示左箭头
void display_left_arrow()
{
    lcd_display_bytes_in_page(4, 40, LEFT_ARROW, 4);
}

// 显示右箭头
void display_right_arrow()
{
    lcd_display_bytes_in_page(4, 80, RIGHT_ARROW, 4);
}

// 清除数字显示区域
void clear_speed_number_area()
{
    unsigned char i;
    lcd_write_command(0xB8 | 4, 0); // 选择第4页，左屏
    lcd_write_command(0x40 | 60, 0); // 设置列地址
    for (i = 0; i < 4; i++)
    {
        lcd_write_data(0x00, 0);
    }
}

// 更新整个Speed界面
void update_speed_display()
{
    clear_speed_number_area();
    display_speed_text();
    display_left_arrow();
    display_speed_number();
    display_right_arrow();
}

// 处理按键事件
void handle_button_press(unsigned char btn_code)
{
    switch (btn_code)
    {
        case BTN_CODE_LEFT:
            if (current_speed > SPEED_MIN)
            {
                current_speed--;
                update_speed_display();
            }
            break;

        case BTN_CODE_RIGHT:
            if (current_speed < SPEED_MAX)
            {
                current_speed++;
                update_speed_display();
            }
            break;

        default:
            break;
    }
}

void main()
{
    unsigned char pressed_btn;

    // 初始化LCD
    lcd_init();
    lcd_clear_screen();

    // 显示初始界面
    update_speed_display();

    while (1)
    {
        pressed_btn = btn_scan();
        if (pressed_btn != BTN_CODE_NONE)
        {
            handle_button_press(pressed_btn);
        }
    }
}